/*
Acess v0.1
Module Loader Version 2
*/
#include <acess.h>

// CONSTANTS
#define NUM_STATIC_MODULES	(((Uint)&gKernelModulesEnd-(Uint)&gKernelModules)/sizeof(struct sKernelModule))

// === TYPES ===
typedef struct sModule {
	char	*Name;
	Uint	Version;	// BCD
	 int	(*Load)();
	 int	(*Unload)();
	Uint	Base;
	struct sModule	*Next;
} tModule;

// === IMPORTS ===
extern void	gKernelModulesEnd;
extern struct sKernelModule	gKernelModules[];

// === GLOBALS ===
tModule	*gFirstModule = NULL;

// === CODE ===
/**
 * \fn void Module_InstallStatics()
 * \brief Install (Initialise) Staticly compiled modules
 */
void Module_InstallStatics()
{
	 int	i;
	LogF("[MOD ] %i Static Modules\n", NUM_STATIC_MODULES);
	for(i=0;i<NUM_STATIC_MODULES;i++)
	{
		LogF("[MOD ] Installing Static '%s'...\n", gKernelModules[i].Name);
		gKernelModules[i].Init(NULL);
	}
}

/**
 * \fn int Module_Load(char *path)
 * \brief Loads a module from the specified file
 */
int Module_Load(char *path)
{
	Uint	iBase;
	tModule	*info;
	
	// Load Module
	iBase = Binary_LoadKernel(path);
	if(!iBase) {
		WarningEx("MOD", "Unable to load '%s' as a kernel module, does not exist or unknown type\n", path);
		return 0;
	}
	
	// Get information structure
	if( !Binary_GetSymbolBin(iBase, "Module_Info", (Uint*)&info) ) {
		WarningEx("MOD", "Unable to load '%s' as a kernel module, no module header\n", path);
		Binary_Unload( iBase );
		return 0;
	}
	
	// Set kernel's values
	info->Base = iBase;
	
	// Call Entrypoint
	info->Load();
	
	// Append to list
	info->Next = gFirstModule;
	gFirstModule = info;
	
	// Print Loaded message
	LogF("[MOD ] Loaded '%s' (%s)\n", info->Name, path);
	return 1;
}
